#ifndef _ITRACE_H_
#define _ITRACE_H_

#include "types.h"
#include "utils.h"

struct TraceRecord {
    word_t pc;
    uint32_t inst;
};

class ITrace {
private:
    int size;
    TraceRecord* ringbuf;
    int front, rear;
    std::FILE* fp;
public:
    bool enable { false };
    ITrace(const char* file, int size = 24): rear(0), front(0), size(size) {
        ringbuf = new TraceRecord[size];
        fp = std::fopen(file, "w");
        Log("The instruction trace file is %s", file);
        if (fp == NULL) {
            Panic("Open file error!\n");
        }
    }
    ~ITrace() {
        std::fclose(fp);
        delete [] ringbuf;
    }
    void add(word_t pc, uint32_t inst) {
        ringbuf[rear].pc = pc;
        ringbuf[rear].inst = inst;
        rear = (rear + 1) % size;
        if (rear == front) {
            front = (front + 1) % size;
        }
        if (!enable) return;
        std::fprintf(fp, FMT_WORD ": 0x%08x\n", pc, inst);
        std::fflush(fp);
    }
    void print() {
        int i = front;
        while (i != rear) {
            std::printf("\t" FMT_WORD ": 0x%08x\n", ringbuf[i].pc, ringbuf[i].inst);
            i = (i + 1) % size;
        }
    }
};

#endif
